﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Linq;
using CNative.Utilities;

namespace CNative.Dapper.Utils
{
//#if !NET40
    internal class PostgreSqlProvider : BaseProvider
    {
        public PostgreSqlProvider(IDbHelper _db) : base(_db)
        {
        }
        #region 关键字
        /// <summary>
        /// 数据库提供程序名字
        /// </summary>
        public override string ProviderName
        {
            get
            {
                return "Npgsql";
            }
        }
        public override string ProviderNameFactory
        {
            get
            {
                return "Npgsql.NpgsqlFactory";
            }
        }
        /// <summary>
        /// 数据库类型
        /// </summary>
        public override DatabaseType DBType { get { return DatabaseType.PostgreSql; } }
        /// <summary>
        /// 参数关键字 @
        /// </summary>
        public override string ParamKeyword
        {
            get
            {
                return "@";
            }
        }
        /// <summary>
        /// 关键字前缀 \"
        /// </summary>
        public override string SuffixLeft
        {
            get
            {
                return "\"";
            }
        }
        /// <summary>
        /// 关键字后缀 \"
        /// </summary>
        public override string SuffixRigh
        {
            get
            {
                return "\"";
            }
        }
        #endregion

        #region DbProviderFactory
        public override string GetSchemaTableName(Type tableType)
        {
            var tb = Funs.GetDbTableInfo(dbHelper, tableType);
            if (tb == null)
            {
                return "";
            }
            return tb.Schema.IsNullOrEmpty() ? tb.TableName :"public." + tb.TableName;
        }
        #endregion

        #region GetDbParameter
        ///// <summary>
        ///// 获取DbParameter
        ///// </summary>
        ///// <param name="dbType">数据库类型</param>
        ///// <returns></returns>
        //public override IDataParameter GetDbParameter(string propName, object val, string paramSuffix = "exp_",
        //    DbTableInfo tb = null, ParameterDirection direction = ParameterDirection.Input, DbType valDBType = DbType.String)
        //{
        //    IDataParameter para = null;
        //    //--------------------------------------------------------------------------------------------------------------
        //    var frets = FillerParameter(propName, val, paramSuffix);
        //    if (frets.Item1)
        //    {
        //        return para;
        //    }
        //    var parameterName = frets.Item2;
        //    val = frets.Item3;
        //    //--------------------------------------------------------------------------------------------------------------
        //    #region Npgsql
        //    if (direction == ParameterDirection.Output)
        //    {
        //        para = new Npgsql.NpgsqlParameter()
        //        {
        //            ParameterName = parameterName,
        //            Value = val,
        //            DbType = valDBType,
        //            Direction = direction
        //        };
        //        return para;
        //    }

        //    para = new Npgsql.NpgsqlParameter()
        //    {
        //        ParameterName = parameterName,
        //        Value = val,
        //        Direction = direction
        //    };
        //    if (tb != null && tb.TableInfo != null)
        //    {
        //        var dtinfo = tb.TableInfo.Find(f => f.Name.Equals(propName.Trim(), StringComparison.OrdinalIgnoreCase));
        //        if (dtinfo != null)
        //        {
        //            try
        //            {
        //                (para as Npgsql.NpgsqlParameter).NpgsqlDbType = NpgsqlTypeString2SqlType(dtinfo.Type);// dtinfo.Type.ToEnum<MySqlDbType>();
        //                if (dtinfo.MaxLength > 0 && dtinfo.MaxLength < int.MaxValue)
        //                    (para as Npgsql.NpgsqlParameter).Size = (int)dtinfo.MaxLength;
        //            }
        //            catch { }
        //        }
        //    }
        //    #endregion
        //    return para;
        //}
        //private NpgsqlTypes.NpgsqlDbType NpgsqlTypeString2SqlType(string sqlTypeString)
        //{
        //    var dbType = NpgsqlTypes.NpgsqlDbType.Varchar; //默认为Object
        //    sqlTypeString = sqlTypeString.Trim().ToLower();

        //    var parameterType = GetParameterTypeName(sqlTypeString);
        //    dbType = parameterType.ToEnum<NpgsqlTypes.NpgsqlDbType>();
        //    return dbType;
        //}
        #endregion
        #region MappingTypes
        /// <summary>
        /// 类型映射
        /// sqlTypeName，CsharpType，ParameterType
        /// </summary>
        public override List<Tuple<string, string, string>> MappingTypes
        {
            get
            {
                return new List<Tuple<string, string, string>>()
                    {
                        Tuple.Create("int8","Int64","Bigint"),
                        Tuple.Create("bool","Boolean","Boolean"),
                        Tuple.Create("bytea","byte[]","Bytea"),
                        Tuple.Create("date","DateTime","Date"),
                        Tuple.Create("float8","Double","Double"),
                        Tuple.Create("int4","int","Integer"),
                        Tuple.Create("money","Decimal","Money"),
                        Tuple.Create("numeric","Decimal","Numeric"),
                        Tuple.Create("float4","Single","Real"),
                        Tuple.Create("int2","short","Smallint"),
                        Tuple.Create("text","string","Text"),
                        Tuple.Create("time","DateTime","Time"),
                        Tuple.Create("timetz","DateTime","Time"),
                        Tuple.Create("timestamp","DateTime","Timestamp"),
                        Tuple.Create("timestamptz","DateTime","TimestampTZ"),
                        Tuple.Create("interval","TimeSpan","Interval"),
                        Tuple.Create("varchar","string","Varchar"),
                        Tuple.Create("inet","IPAddress","Inet"),
                        Tuple.Create("bit","Boolean","Bit"),
                        Tuple.Create("uuid","Guid","Uuid"),
                        Tuple.Create("array","Array","Array")
                    };
            }
        }

        /// <summary>
        /// 获取库类型
        /// </summary>
        /// <param name="csharpTypeName"></param>
        /// <returns></returns>
        public override string GetDbTypeName(string csharpTypeName)
        {
            if (csharpTypeName == Constants.ByteArrayType.Name)
                return "bytea";
            csharpTypeName = CheckCsharpTypeName(csharpTypeName);
            var mappings = this.MappingTypes?.Where(it => it.Item2.Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)).ToList();
            if (mappings != null && mappings.Count > 0)
                return mappings.First().Item1;
            else
                return "varchar";
        }
        /// <summary>
        /// 获取sql Parameter Type
        /// </summary>
        /// <param name="dbTypeName"></param>
        /// <returns></returns>
        public override string GetParameterTypeName(string dbTypeName)
        {
            var mappings = this.MappingTypes?.Where(it => it.Item1.Equals(dbTypeName, StringComparison.CurrentCultureIgnoreCase));
            return !mappings.IsNullOrEmpty_() ? mappings.First().Item3 : "Varchar";
        }
        #endregion

        #region Sql Fun Templet
        /// <summary>
        /// SQL NVL() 从两个表达式返回一个非 null 值	函数
        /// </summary>
        /// <param name="check_expression">将被检查是否为 NULL的表达式。可以是任何类型的。</param>
        /// <param name="replacement_value">在 check_expression 为 NULL时将返回的表达式。replacement_value 必须与 check_expresssion 具有相同的类型。</param>
        /// <returns>如果 check_expression 不为 NULL，那么返回该表达式的值；否则返回 replacement_value</returns>
        public override string SQL_NVL(string check_expression, string replacement_value)
        {
            return $"IFNULL({check_expression},{replacement_value})";
        }
        /// <summary>
        /// 获取数据库时间函数
        /// </summary>
        public override string SqlDateNow
        {
            get
            {
                return "NOW()"; //" NOW() ";
            }
        }
        /// <summary>
        /// 获取当前时间sql语句
        /// </summary>
        public override string FullSqlDateNow
        {
            get
            {
                return "select NOW()";
            }
        }

        /// <summary>
        /// SQL UCASE() 函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="column_name">列名</param>
        /// <returns>函数把字段的值转换为大写</returns>
        public override string SQL_UCASE(string column_name)
        {
            return $"UPPER({column_name})";
        }

        /// <summary>
        /// SQL LCASE() 函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="column_name">列名</param>
        /// <returns>函数把字段的值转换为小写</returns>
        public override string SQL_LCASE(string column_name)
        {
            return $"LOWER({column_name})";
        }

        /// <summary>
        /// SQL LEFT(s,n) 函数
        /// </summary>
        /// <param name="str">列名</param>
        /// <returns>返回字符串 str 的前 length 个字符</returns>
        public override string SQL_LEFT(string str, int length)
        {
            return $"LEFT({str},{length})";
        }
        /// <summary>
        /// SQL RIGHT(s,n) 函数
        /// </summary>
        /// <param name="str">列名</param>
        /// <returns>返回字符串 str 的前 length 个字符</returns>
        public override string SQL_RIGHT(string str, int length)
        {
            return $"RIGHT({str},{length})";
        }
        /// <summary>
        /// SQL SUBSTR(s, start, length) 函数
        /// </summary>
        /// <param name="str">列名</param>
        /// <returns>从字符串 str 的 start 位置截取长度为 length 的子字符串</returns>
        public override string SQL_SUBSTR(string str, int start, int length)
        {
            return $"substr({str},{1 + start},{length})";
        }
        /// <summary>
        /// SQL TRIM(s) 函数
        /// </summary>
        /// <param name="str">列名</param>
        /// <returns>去掉字符串 str 开始和结尾处的空格</returns>
        public override string SQL_TRIM(string str)
        {
            return $"TRIM({str})";
        }
        /// <summary>
        /// SQL CAST() 转换数据类型	函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="column_name">列名</param>
        /// <param name="type">数据类型</param>
        /// <returns>转换数据类型</returns>
        public override string SQL_CAST(string column_name, string type)
        {
            return $"CAST({column_name} AS {type})";
        }

        public override string SQL_ToInt32(string column_name)
        {
            return SQL_CAST(column_name, "INT4");
        }

        public override string SQL_ToInt64(string column_name)
        {
            return SQL_CAST(column_name, "INT8");
        }
        public override string SQL_ToDouble(string column_name)
        {
            return SQL_CAST(column_name, "DECIMAL(18,4)");
        }
        /// <summary>转换高精度的十进制数（一般用于货币）</summary>
        /// <param name="column_name"></param>
        /// <param name="d">小数位数</param>
        /// <returns></returns>
        public override string SQL_ToDecimal(string column_name, int d)
        {
            if (d < 0 || d > 10) d = 4;
            return SQL_CAST(column_name, "DECIMAL(18, " + d + ")");
        }

        public override string SQL_ToBool(string column_name)
        {
            return SQL_CAST(column_name, "boolean");
        }

        public override string SQL_ToVarchar(string column_name)
        {
            return SQL_CAST(column_name, "VARCHAR");
        }

        public override string SQL_ToGuid(string column_name)
        {
            return SQL_CAST(column_name, "VARCHAR");
        }

        public override string SQL_ToDate(string column_name)
        {
            return SQL_CAST(column_name, "DATETIME");
        }

        public override string SQL_ToDateShort(string column_name)
        {
            return SQL_CAST(column_name, "DATE");
        }

        public override string SQL_ToTime(string column_name)
        {
            return SQL_CAST(column_name, "TIME");
        }
        #endregion

        #region SqlTemplet
        /// <summary>
        /// 一般查询语句模板
        /// </summary>
        /// <param name="tbname"></param>
        /// <param name="fieldsstr"></param>
        /// <param name="orderbyStr"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        public override string GetSelectSQL(String tbname, string fieldsstr, string orderbyStr, int top = 0)
        {
            var sqlMeta = @"SELECT " + fieldsstr + " FROM " + tbname + " WHERE {0} " + orderbyStr + (top > 0 ? " limit " + top + " OFFSET 0 " : "");
            return sqlMeta;
        }
        /// <summary>
        /// 分页查询语句模板
        /// </summary>
        /// <param name="tbName">表名</param>
        /// <param name="fieldsstr"></param>
        /// <param name="whereStr"></param>
        /// <param name="orderbyStr"></param>
        /// <param name="page">当前页面</param>
        /// <param name="nums">每页记录数</param>
        /// <returns></returns>
        public override string GetSelectPageSQL(string tbName, string fieldsstr, string whereStr, string orderbyStr, int page = 1, int nums = 25)
        {
            if (page < 1) page = 1;
            if (nums < 1) nums = 10;
            var m = (page - 1) * nums;// + 1;
            var n = nums;// page * nums;

            var sqlMeta = $"SELECT {fieldsstr} FROM {tbName} WHERE {whereStr } {orderbyStr} limit {n} OFFSET {m} ";
            return sqlMeta;
        }
        /// <summary>
        /// MERGE 合并语句模板
        /// </summary>
        /// <param name="_dbType"></param>
        /// <param name="tbname"></param>
        /// <returns></returns>
        public override string GetMergeSql(String tbname)
        {
            var sqlMeta = @"MERGE " + tbname + " AS [target]  USING(SELECT 1 AS ____Id_____) AS source ON {0}  WHEN MATCHED THEN {1}  WHEN NOT MATCHED THEN {2};";

            return sqlMeta;
        }

        /// <summary>
        /// 更新语句模板
        /// "UPDATE " + (isMerge ? "" : fromStr) + " SET {0} " + (isMerge ? "" : " WHERE {1} ")
        /// </summary>
        /// <param name="_dbType"></param>
        /// <param name="fromStr"></param>
        /// <param name="isMerge">是参与MERGE</param>
        /// <returns></returns>
        public override string GetUpdateSql(String fromStr, bool isMerge = false)
        {
            var sqlMeta = "UPDATE " + (isMerge ? "" : fromStr) + " SET {0} " + (isMerge ? "" : " WHERE {1} ");

            return sqlMeta;
        }
        /// <summary>
        /// 插入语句模板
        /// "INSERT " + (isMerge ? "" : " INTO " + fromStr) + " ({0}) VALUES ({1})"
        /// </summary>
        /// <param name="_dbType"></param>
        /// <param name="fromStr"></param>
        /// <param name="isMerge">是参与MERGE</param>
        /// <returns></returns>
        public override string GetInsertSql(String fromStr, bool isMerge = false)
        {
            var sqlMeta = "INSERT " + (isMerge ? "" : " INTO " + fromStr) + " ({0}) VALUES ({1})";

            return sqlMeta;
        }
        /// <summary>
        /// 统计数量语句模板
        /// $"SELECT Count(0) FROM {fromStr} WHERE {0}";
        /// </summary>
        /// <param name="_dbType"></param>
        /// <param name="fromStr"></param>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public override string GetCountSql(String fromStr, string fieldName = "")
        {
            var sqlMeta = "SELECT Count(" + (fieldName.IsNullOrEmpty() ? "0" : fieldName) + ") FROM " + fromStr + " WHERE {0}";

            return sqlMeta;
        }
        /// <summary>
        /// GetInsertSelectSql
        /// INSERT INTO " + insertTable + " ({0}) " + " SELECT {1} FROM " + selectTable + "  WHERE {2} 
        /// </summary>
        /// <param name="insertTable"></param>
        /// <param name="selectTable"></param>
        /// <param name="_dbType"></param>
        /// <returns></returns>
        public override string GetInsertSelectSql(String insertTable, String selectTable)
        {
            var sqlMeta = "INSERT INTO " + insertTable + " ({0}) " +
                            " SELECT {1} FROM " + selectTable + "  WHERE {2} ";

            return sqlMeta;
        }
        #endregion

        #region WithNextSequence
        /// <summary>
        /// 下个序列脚本
        /// </summary>
        /// <param name="sequenceName"></param>
        /// <returns></returns>
        public override string WithNextSequence(string sequenceName = null)
        {
            if (string.IsNullOrEmpty(sequenceName))
            {
                sequenceName = "default_seq";
            }
            return $"nextval('{sequenceName}')";
        }
        #endregion

        #region DML CodeFirst
        /// <summary>
        /// 获取所有数据库
        /// </summary>
        public override string GetDataBaseSql
        {
            get
            {
                return "select pg_database.datname as name/*, pg_database_size(pg_database.datname) AS size*/ from pg_database";
            }
        }
        /// <summary>
        /// 获取数据库中的所有表
        /// </summary>
        public override string GetTableInfoListSql
        {
            get
            {
                return @"/*{0}*/select cast(relname as varchar) as Name,
                        cast(obj_description(relfilenode,'pg_class') as varchar) as Description from pg_class c 
                        where  relkind = 'r' and relname not like 'pg_%' and relname not like 'sql_%' order by relname";
            }
        }
        /// <summary>
        /// 获取数据库中的所有视图
        /// </summary>
        public override string GetViewInfoListSql
        {
            get
            {
                return @"/*{0}*/select cast(relname as varchar) as Name,cast(Description as varchar) from pg_description
                         join pg_class on pg_description.objoid = pg_class.oid
                         where objsubid = 0 and relname in (SELECT viewname from pg_views  
                         WHERE schemaname ='public')";
            }
        }
        /// <summary>
        /// 得到一个表的所有列信息
        /// </summary>
        public override string GetColumnInfosByTableNameSql
        {
            get
            {
                return @"/*{0}*/select cast (pclass.oid as int4) as TableId,cast(ptables.tablename as varchar) as TableName,
																cast(ptables.tablename as varchar) as table_name,
																ORDINAL_POSITION AS ColumnId," +
                               " pcolumn.column_name as \"Name\",pcolumn.udt_name as \"Type\","+
                               @" pcolumn.character_maximum_length as MaxLength,
                                pcolumn.column_default as DefaultValue,
                                col_description(pclass.oid, pcolumn.ordinal_position) as Description,
                                case when pkey.colname = pcolumn.column_name
                                then true else false end as IsPrimaryKey,
                                case when pcolumn.column_default like 'nextval%'
                                then true else false end as IsIdentity,
                                case when pcolumn.is_nullable = 'YES'
                                then true else false end as IsNullable
                                 from(select * from pg_tables where upper(tablename) = upper('{1}') and schemaname = 'public') ptables inner join pg_class pclass
                                 on ptables.tablename = pclass.relname inner join(SELECT*
                                 FROM information_schema.columns
 
                                 ) pcolumn on pcolumn.table_name = ptables.tablename
                                left join(
                                    select pg_class.relname, pg_attribute.attname as colname 
                                    from pg_constraint inner join pg_class on pg_constraint.conrelid = pg_class.oid
                                   inner join pg_attribute on pg_attribute.attrelid = pg_class.oid                                                   
                                        and  pg_attribute.attnum = pg_constraint.conkey[1]
                                   inner join pg_type on pg_type.oid = pg_attribute.atttypid
                                    where pg_constraint.contype = 'p'
                                ) pkey on pcolumn.table_name = pkey.relname
                                where upper(ptables.tablename)=upper('{1}')
                                order by ORDINAL_POSITION;";
            }
        }
        #endregion

        #region DDL
        public override IDbFirst DbFirst { get { return new PostgreSQLDbFirst(this.dbHelper.DBName); } }

        #region DDL SQL
        protected override string CreateDataBaseSql
        {
            get
            {
                return "CREATE DATABASE {0}";
            }
        }
        protected override string AddPrimaryKeySql
        {
            get
            {
                return "ALTER TABLE {0} ADD PRIMARY KEY({2}) /*{1}*/";
            }
        }
        protected override string AddColumnToTableSql
        {
            get
            {
                return "ALTER TABLE {0} ADD COLUMN {1} {2}{3} {4} {5} {6}";
            }
        }
        protected override string AlterColumnToTableSql
        {
            get
            {
                return "alter table {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}";
            }
        }
        protected override string BackupDataBaseSql
        {
            get
            {
                return "mysqldump.exe  {0} -uroot -p > {1}  ";
            }
        }
        protected override string CreateTableSql
        {
            get
            {
                return "CREATE TABLE {0}(\r\n{1} $PrimaryKey)";
            }
        }
        protected override string CreateTableColumn
        {
            get
            {
                return "{0} {1}{2} {3} {4} {5}";
            }
        }
        protected override string TruncateTableSql
        {
            get
            {
                return "TRUNCATE TABLE {0}";
            }
        }
        protected override string BackupTableSql
        {
            get
            {
                return "create table {0} as (select * from {1} limit {2} offset 0)";
            }
        }
        protected override string DropTableSql
        {
            get
            {
                return "DROP TABLE {0}";
            }
        }
        protected override string DropColumnToTableSql
        {
            get
            {
                return "ALTER TABLE {0} DROP COLUMN {1}";
            }
        }
        protected override string DropConstraintSql
        {
            get
            {
                return "ALTER TABLE {0} DROP CONSTRAINT {1}";
            }
        }
        protected override string RenameColumnSql
        {
            get
            {
                return "ALTER TABLE {0} RENAME {1} TO {2}";
            }
        }
        protected override string AddColumnRemarkSql => "comment on column {1}.{0} is '{2}'";

        protected override string DeleteColumnRemarkSql => "comment on column {1}.{0} is ''";

        protected override string IsAnyColumnRemarkSql { get { throw new NotSupportedException(); } }

        protected override string AddTableRemarkSql => "comment on table {0} is '{1}'";

        protected override string DeleteTableRemarkSql => "comment on table {0} is ''";

        protected override string IsAnyTableRemarkSql { get { throw new NotSupportedException(); } }

        protected override string RenameTableSql => "alter table 表名 {0} to {1}";

        protected override string CreateIndexSql
        {
            get
            {
                return "CREATE {3} INDEX Index_{0}_{2} ON {0} ({1})";
            }
        }
        protected override string AddDefaultValueSql
        {
            get
            {
                return "ALTER TABLE {0} ALTER COLUMN {1} SET DEFAULT {2}";
            }
        }
        protected override string IsAnyIndexSql
        {
            get
            {
                return "  Select count(1) from (SELECT to_regclass('{0}') as c ) t where t.c is not null";
            }
        }

        #endregion

        #region Check
        protected override string CheckSystemTablePermissionsSql
        {
            get
            {
                return "select 1 from information_schema.columns limit 1 offset 0";
            }
        }
        #endregion

        #region Scattered
        protected override string CreateTableNull
        {
            get
            {
                return "DEFAULT NULL";
            }
        }
        protected override string CreateTableNotNull
        {
            get
            {
                return "NOT NULL";
            }
        }
        protected override string CreateTablePirmaryKey
        {
            get
            {
                return "PRIMARY KEY";
            }
        }
        protected override string CreateTableIdentity
        {
            get
            {
                return "serial";
            }
        }
        #endregion

        #region Methods
        public override bool UpdateColumn(string tableName, DbColumnInfo columnInfo)
        {
            tableName = this.GetTranslationTableName(tableName);
            var columnName = this.GetTranslationColumnName(columnInfo.Name);

            string sql = GetUpdateColumnSql(tableName, columnInfo);
            var sqle = this.dbHelper.CreateSqlEntity(sql);
            this.dbHelper.Execute(sqle);

            var isnull = columnInfo.IsNullable ? " DROP NOT NULL " : " SET NOT NULL ";
            sqle.Sql = string.Format("alter table {0} alter {1} {2}", tableName, columnName, isnull);
            this.dbHelper.Execute(sqle);
            return true;
        }

        protected override string GetUpdateColumnSql(string tableName, DbColumnInfo columnInfo)
        {
            string columnName = this.GetTranslationColumnName(columnInfo.Name);
            tableName = this.GetTranslationTableName(tableName);
            string dataSize = GetSize(columnInfo);
            string dataType = columnInfo.Type;
            if (!string.IsNullOrEmpty(dataType))
            {
                dataType = " type " + dataType;
            }
            string nullType = "";
            string primaryKey = null;
            string identity = null;
            string result = string.Format(this.AlterColumnToTableSql, tableName, columnName, dataType, dataSize, nullType, primaryKey, identity);
            return result;
        }

        /// <summary>
        ///by current connection string
        /// </summary>
        /// <param name="databaseDirectory"></param>
        /// <returns></returns>
        public override bool CreateDatabase(string databaseName, string databaseDirectory = null)
        {
            if (databaseDirectory != null)
            {
                if (!FileHelper.IsExistDirectory(databaseDirectory))
                {
                    FileHelper.CreateDirectory(databaseDirectory);
                }
            }
            var newDb = new DbHelper(this.dbHelper.DBName);
            var oldDatabaseName = Connection.Database;
            var connection = this.dbHelper.ConnectString;
            connection = connection.Replace(oldDatabaseName, "postgres");
            newDb.ConnectString = connection;
            if (!GetDataBaseList(newDb).Any(it => it.Equals(databaseName, StringComparison.CurrentCultureIgnoreCase)))
            {
                var sql = string.Format(string.Format(CreateDataBaseSql, this.SuffixLeft + databaseName + this.SuffixRigh, databaseDirectory));
                var sqle = newDb.CreateSqlEntity(sql);
                newDb.Execute(sqle);
            }
            return true;
        }
        public override bool AddRemark(DbTableInfo entity)
        {
            var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList();

            foreach (var item in columns)
            {
                if (item.Description != null)
                {
                    AddColumnRemark(item.Name, entity.TableName, item.Description);

                }
            }
            //table remak
            if (entity.Description != null)
            {
                AddTableRemark(entity.TableName, entity.Description);
            }
            return true;
        }
        public override bool CreateTable(string tableName, List<DbColumnInfo> columns, bool isCreatePrimaryKey = true)
        {
            if (columns.HasValue())
            {
                foreach (var item in columns)
                {
                    if (item.Name.Equals("GUID", StringComparison.CurrentCultureIgnoreCase) && item.MaxLength == 0)
                    {
                        item.MaxLength = 10;
                    }
                }
            }
            string sql = GetCreateTableSql(tableName, columns);
            string primaryKeyInfo = null;
            if (columns.Any(it => it.IsPrimaryKey) && isCreatePrimaryKey)
            {
                primaryKeyInfo = string.Format(", Primary key({0})", string.Join(",", columns.Where(it => it.IsPrimaryKey).Select(it => this.GetTranslationColumnName(it.Name.ToLower()))));

            }
            sql = sql.Replace("$PrimaryKey", primaryKeyInfo);
            var sqle = this.dbHelper.CreateSqlEntity(sql);
            this.dbHelper.Execute(sqle);
            return true;
        }
        protected override string GetCreateTableSql(string tableName, List<DbColumnInfo> columns)
        {
            List<string> columnArray = new List<string>();
            Check.Exception(columns.IsNullOrEmpty(), "No columns found ");
            foreach (var item in columns)
            {
                string columnName = item.Name;
                string dataType = item.Type;
                if (dataType == "varchar" && item.MaxLength == 0)
                {
                    item.MaxLength = 1;
                }
                if (dataType == "uuid")
                {
                    item.MaxLength = 50;
                    dataType = "varchar";
                }
                string dataSize = item.MaxLength > 0 ? string.Format("({0})", item.MaxLength) : null;
                string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull;
                string primaryKey = null;
                string addItem = string.Format(this.CreateTableColumn, this.GetTranslationColumnName(columnName.ToLower()), dataType, dataSize, nullType, primaryKey, "");
                if (item.IsIdentity)
                {
                    string length = dataType.Substring(dataType.Length - 1);
                    string identityDataType = "serial" + length;
                    addItem = addItem.Replace(dataType, identityDataType);
                }
                columnArray.Add(addItem);
            }
            string tableString = string.Format(this.CreateTableSql, this.GetTranslationTableName(tableName.ToLower()), string.Join(",\r\n", columnArray));
            return tableString;
        }
        public override bool IsAnyConstraint(string constraintName)
        {
            throw new NotSupportedException("PgSql IsAnyConstraint NotSupportedException");
        }
        public override bool BackupDataBase(string databaseName, string fullFileName)
        {
            Check.ThrowNotSupportedException("PgSql BackupDataBase NotSupported");
            return false;
        }

        public override List<DbColumnInfo> GetColumnInfosByTableName(string tableName, string dbName, bool isCache = true)
        {
            return base.GetColumnInfosByTableName(tableName.TrimEnd('"').TrimStart('"').ToLower(),dbName, isCache);
        }
        #endregion
        #endregion
    }
    //#endif
}
